﻿#include "displaywind.h"
#include "ui_displaywind.h"
#include <QDebug>
#include <QPainter>
#include <QOpenGLTexture>
#include <QOpenGLShaderProgram>
#include "easylogging++.h"
#include <QRandomGenerator>
#include  "../../../../DevSoft/LearingOpenGL/include/stb_image.h"

#define VERTEXIN 0
#define TEXTUREIN 1
DisplayWind::DisplayWind(QWidget *parent) :
    QOpenGLWidget(parent),
    ui(new Ui::DisplayWind)
{
    ui->setupUi(this);
    win_width_ = width();
    win_height_ = height();
    memset(&dst_video_frame_, sizeof(VideoFrame), 0);
    play_state_ = 2;
  //  setAttribute(Qt::WA_StyledBackground);
    //setStyleSheet("background: black");
    dump_yuv = fopen("dump_op_yuv.yuv","wb");
}

DisplayWind::~DisplayWind()
{
    QMutexLocker locker(&m_mutex);
    delete ui;
    DeInit();
}



GLfloat vers2[] = {
    //顶点坐标
    -1.0f,-1.0f, 0.0f,  0.0f,1.0f,
    -1.0f,+1.0f, 0.0f,  0.0f,0.0f,
    +1.0f,+1.0f, 0.0f,  1.0f,0.0f,
    +1.0f,-1.0f, 0.0f,  1.0f,1.0f
//    0.0f,0.5f, 0.0f,     0.5f,0.0f,
//    0.0f,-0.5f,0.0f,     0.0f,0.5f
    //纹理坐标
};

GLfloat vers3[] = {
    //顶点坐标
    -1.0f,-1.0f, 0.0f,  0.0f,0.0f,

    -1.0f,+1.0f, 0.0f,  0.0f,1.0f,
    +1.0f,+1.0f, 0.0f,  1.0f,1.0f,
    +1.0f,-1.0f, 0.0f,  1.0f,0.0f
    //纹理坐标
};

GLfloat vers[] = {
    -0.5f,-0.5f,0.0f, 0,0,
    0.5f,-0.5f,0.0f,  1,0,
    -0.5f,0.5f,0.0f,  0,1,
    0.5f,0.5f,0.0f,  1,1
};

GLuint indecs[] = {
  0,1,2,3,4,5
};


void  DisplayWind::initVAO()
{
//    glGenVertexArrays(1, &VAO);
//    glGenBuffers(1, &VBO);
//    glGenBuffers(1, &EBO);

//    glBindVertexArray(VAO);
//    glBindBuffer(GL_ARRAY_BUFFER,VBO);
//    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO);

//    glBufferData(GL_ARRAY_BUFFER,sizeof (vers),vers,GL_STATIC_DRAW);
//    glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof (indecs),indecs,GL_STATIC_DRAW);
//    glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,5*sizeof (GLfloat),0);
//    glEnableVertexAttribArray(0);
//    glVertexAttribPointer(1,2,GL_FLOAT,GL_FALSE,5*sizeof(GLfloat),(void*)(3*sizeof(GLfloat)));
//    glEnableVertexAttribArray(1);




//    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
//    glBindBuffer(GL_ARRAY_BUFFER,0);
//    glBindVertexArray(0);
}

void  DisplayWind::initShader()
{
//    int vShader = glCreateShader(GL_VERTEX_SHADER);
//    glShaderSource(vShader,1,&vertexShaderSource,NULL);
//    glCompileShader(vShader);

//    int fragShader = glCreateShader(GL_FRAGMENT_SHADER);
//    glShaderSource(fragShader,1,&fragmentShaderSource,NULL);
//    glCompileShader(fragShader);

//    g_shaderprogram = glCreateProgram();
//    glAttachShader(g_shaderprogram,vShader);
//    glAttachShader(g_shaderprogram,fragShader);
//    glLinkProgram(g_shaderprogram);

//    glUseProgram(g_shaderprogram);
//    glDeleteShader(vShader);
//    glDeleteShader(fragShader);

}


int DisplayWind::Draw(const Frame *frame)
{
    QMutexLocker locker(&m_mutex);

    if(!img_scaler_ || req_resize_) {
        if(img_scaler_) {
            DeInit();
        }
        win_width_ = width();
        win_height_ = height();
        video_width = frame->width;
        video_height = frame->height;
        img_scaler_ = new ImageScaler();
        double video_aspect_ratio = frame->width * 1.0 / frame->height;
        double win_aspect_ratio = win_width_ * 1.0 / win_height_;
        if(win_aspect_ratio > video_aspect_ratio) {
            //此时应该是调整x的起始位置，以高度为基准
            img_height = win_height_;
            img_height &= 0xfffc;
            img_width = img_height * video_aspect_ratio;
            img_width &= 0xfffc;
            y_ = 0;
            x_ = (win_width_ - img_width) / 2;
        } else {
            //此时应该是调整y的起始位置，以宽度为基准
            img_width = win_width_;
            img_width &= 0xfffc;
            img_height = img_width / video_aspect_ratio;
            img_height &= 0xfffc;
            x_ = 0;
            y_ = (win_height_ - img_height) / 2;
        }
        img_width = (img_width >> 4) << 4;
        img_height = (img_height >> 4) << 4;

        LOG(ERROR) << frame->frame->format << " " << frame->frame->width << " " << frame->frame->height;


//        img_width = 128,img_height=128;
        img_width = frame->width, img_height = frame->height + 8;
        img_scaler_->Init(video_width, video_height, frame->format,
                          img_width, img_height, AV_PIX_FMT_RGB24);
        memset(&dst_video_frame_, 0, sizeof(VideoFrame));
        dst_video_frame_.width = img_width;
        dst_video_frame_.height = img_height;
        dst_video_frame_.format = AV_PIX_FMT_RGB24;
        dst_video_frame_.data[0] = (uint8_t*)malloc(img_width * img_height * 3);
//        dst_video_frame_.data[1] =  dst_video_frame_.data[0] + img_width * img_height;
//        dst_video_frame_.data[2] =   dst_video_frame_.data[0] + img_width * img_height * 5/ 4;
        dst_video_frame_.linesize[0] = img_width *3 ; // 每行的字节数
//        dst_video_frame_.linesize[1] = img_width /2 ;
//        dst_video_frame_.linesize[2] = img_width /2;
        videoW = img_width,videoH=img_height;
       // fwrite(dst_video_frame_.data[0],1,img_width*img_height*1.5,dump_yuv);
        req_resize_ = false;
    }
    img_scaler_->Scale3(frame, &dst_video_frame_);
    //fwrite(dst_video_frame_.data[0],1,dst_video_frame_.width*dst_video_frame_.height*1.5,dump_yuv);
    this->yuvPtr = (dst_video_frame_.data[0]);
     videoW = dst_video_frame_.width;
     videoH=dst_video_frame_.height;
//    for(int i = 0; i < dst_video_frame_.height; i++){
//       fwrite(dst_video_frame_.data[0]+i*dst_video_frame_.linesize[0],1,dst_video_frame_.width, dump_yuv);
//    }
//    for(int i = 0; i < dst_video_frame_.height/2; i++){
//          fwrite(dst_video_frame_.data[1]+i*dst_video_frame_.linesize[1],1,dst_video_frame_.width / 2, dump_yuv);
//    }
//    for(int i = 0; i < dst_video_frame_.height/2; i++){
//        fwrite(dst_video_frame_.data[2]+i*dst_video_frame_.linesize[2],1,dst_video_frame_.width / 2, dump_yuv);

//    }

//    QImage imageTmp =  QImage((uint8_t *)dst_video_frame_.data[0],
//                              img_width, img_height, QImage::Format_RGB888);
//    img = imageTmp.copy(0, 0, img_width, img_height);
    update();
    //    repaint();

    return 0;
}
/**
int DisplayWind::Draw(const Frame *frame)
{
    QMutexLocker locker(&m_mutex);

    if(!img_scaler_ || req_resize_) {
        if(img_scaler_) {
            DeInit();
        }
        win_width_ = width();
        win_height_ = height();
        video_width = frame->width;
        video_height = frame->height;
        img_scaler_ = new ImageScaler();
        double video_aspect_ratio = frame->width * 1.0 / frame->height;
        double win_aspect_ratio = win_width_ * 1.0 / win_height_;
        if(win_aspect_ratio > video_aspect_ratio) {
            //此时应该是调整x的起始位置，以高度为基准
            img_height = win_height_;
            img_height &= 0xfffc;
            img_width = img_height * video_aspect_ratio;
            img_width &= 0xfffc;
            y_ = 0;
            x_ = (win_width_ - img_width) / 2;
        } else {
            //此时应该是调整y的起始位置，以宽度为基准
            img_width = win_width_;
            img_width &= 0xfffc;
            img_height = img_width / video_aspect_ratio;
            img_height &= 0xfffc;
            x_ = 0;
            y_ = (win_height_ - img_height) / 2;
        }
        img_width = (img_width >> 4) << 4;
        img_height = (img_height >> 4) << 4;

        LOG(ERROR) << frame->frame->format << " " << frame->frame->width << " " << frame->frame->height;


       img_width = frame->width, img_height = frame->height + 8;
        img_scaler_->Init(video_width, video_height, frame->format,
                          img_width, img_height, AV_PIX_FMT_YUV420P);
        memset(&dst_video_frame_, 0, sizeof(VideoFrame));
        dst_video_frame_.width = img_width;
        dst_video_frame_.height = img_height;
        dst_video_frame_.format = AV_PIX_FMT_YUV420P;
        dst_video_frame_.data[0] = (uint8_t*)malloc(img_width * img_height * 3);
        dst_video_frame_.data[1] =  dst_video_frame_.data[0] + img_width * img_height;
        dst_video_frame_.data[2] =   dst_video_frame_.data[0] + img_width * img_height * 5/ 4;
        dst_video_frame_.linesize[0] = img_width  ; // 每行的字节数
        dst_video_frame_.linesize[1] = img_width /2 ;
        dst_video_frame_.linesize[2] = img_width /2;
        videoW = img_width,videoH=img_height;
       // fwrite(dst_video_frame_.data[0],1,img_width*img_height*1.5,dump_yuv);
        req_resize_ = false;
    }
    img_scaler_->Scale3(frame, &dst_video_frame_);
   // fwrite(dst_video_frame_.data[0],1,dst_video_frame_.width*dst_video_frame_.height*1.5,dump_yuv);
    this->yuvPtr = (dst_video_frame_.data[0]);
     videoW = dst_video_frame_.width;
     videoH=dst_video_frame_.height;
//    for(int i = 0; i < dst_video_frame_.height; i++){
//       fwrite(dst_video_frame_.data[0]+i*dst_video_frame_.linesize[0],1,dst_video_frame_.width, dump_yuv);
//    }
//    for(int i = 0; i < dst_video_frame_.height/2; i++){
//          fwrite(dst_video_frame_.data[1]+i*dst_video_frame_.linesize[1],1,dst_video_frame_.width / 2, dump_yuv);
//    }
//    for(int i = 0; i < dst_video_frame_.height/2; i++){
//        fwrite(dst_video_frame_.data[2]+i*dst_video_frame_.linesize[2],1,dst_video_frame_.width / 2, dump_yuv);

//    }

//    QImage imageTmp =  QImage((uint8_t *)dst_video_frame_.data[0],
//                              img_width, img_height, QImage::Format_RGB888);
//    img = imageTmp.copy(0, 0, img_width, img_height);
    update();
    //    repaint();

    return 0;
}*/

void DisplayWind::DeInit()
{
    if(dst_video_frame_.data[0]) {
        free(dst_video_frame_.data[0]);
        dst_video_frame_.data[0] = NULL;
    }
    if(img_scaler_) {
        delete img_scaler_;
        img_scaler_ = NULL;
    }
}

void DisplayWind::StartPlay()
{
    QMutexLocker locker(&m_mutex);
    play_state_ = 1;
}

void DisplayWind::StopPlay()
{
    QMutexLocker locker(&m_mutex);
    play_state_ = 2;
    update();
}
#define Y 0
#define U 1
#define V 2
void DisplayWind::initTexture()
{
    GLuint nTexture2D[3];
    glGenTextures(3,nTexture2D);
    for(int i = 0; i < 3; i++){
        glBindTexture(GL_TEXTURE_2D, nTexture2D[i]);
        if(i){
            glTexImage2D(GL_TEXTURE_2D,0,GL_RED,dst_video_frame_.width/2,dst_video_frame_.height/2,0,GL_RED,
                         GL_UNSIGNED_BYTE,dst_video_frame_.data[i]);
        }else {
        glTexImage2D(GL_TEXTURE_2D,0,GL_RED,dst_video_frame_.width,dst_video_frame_.height,0,GL_RED,
                     GL_UNSIGNED_BYTE,dst_video_frame_.data[i]);
        }
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
        glBindTexture(GL_TEXTURE_2D,NULL);
    }
//    GLuint nTextureUniform[3];
    nTextureUniform[Y] = glGetUniformLocation(m_shader_program->programId(),"tex_y");
    nTextureUniform[U] = glGetUniformLocation(m_shader_program->programId(),"tex_u");
    nTextureUniform[V] = glGetUniformLocation(m_shader_program->programId(),"tex_v");
    glUniform1i(nTextureUniform[Y],0);
    glUniform1i(nTextureUniform[U],1);
    glUniform1i(nTextureUniform[V],2);
    g_Texture2D[0] = nTexture2D[0];
    g_Texture2D[1] = nTexture2D[1];
    g_Texture2D[2] = nTexture2D[2];
}

/**
 *  yuv.x = texture2D(tex_y, textureOut).r; \
          yuv.y = ((texture2D(tex_u, textureOut)).r -128.0); \
          yuv.z = ((texture2D(tex_v, textureOut)).r -128.0); \
          rgb = mat3( 1.0,       0,         1.402, \
                      1.0,       -0.34414,  -0.7144, \
                      1.0, 1.772,  0) * yuv; \
 * */
//gl_FragColor = vec4(rgb, 1);  //FragColor=vec4(in_color,1.0f);
const char* vertexShaderSource = "#version 330 core\n"
        "layout(location=0) in vec3 aPos;\n"
        "layout(location=1) in vec2 aTexCoord;\n"
        "out vec2 outTexCoord;\n"
        "uniform mat4 transform;\n"
        "void main()\n"
        "{\n"
        "outTexCoord = aTexCoord;\n"
        "gl_Position =  transform * vec4(aPos.x,aPos.y,aPos.z,1.0f);\n"
        "}\n\0";



const char*fragmentShaderSource = "#version 330 core\n"
        "out vec4 FragColor;\n"
        "in vec2 outTexCoord;\n"
         "uniform sampler2D test_tex;\n"
         "uniform sampler2D tex_y;\n"
         "uniform sampler2D tex_u;\n"
         "uniform sampler2D tex_v;\n"
        "uniform vec4 s_color;\n"
        "uniform float temperature; // 调节颜色参数\n"
        "void main()\n"
        "{\n"
        "vec3 rgb;\n"
        "vec3 yuv;\n"
        "yuv.x = texture(tex_y,outTexCoord).r;\n"
        "yuv.y = (texture(tex_u,outTexCoord).r)-0.5f;\n"
        "yuv.z = (texture(tex_v,outTexCoord).r)-0.5f;\n"
        "if(yuv.y > 0.5) yuv.y= 0.5;\n"
         "if(yuv.z >0.5) yuv.z= 0.5;\n"
         "if(yuv.y < -0.5) yuv.y = -0.5;\n"
          "if(yuv.z < -0.5) yuv.z = -0.5;\n"
        "if(yuv.x < 0.0) yuv.x= 0.0;\n"
        "if(yuv.x > 1.0) yuv.x = 1.0;\n"
        "rgb = mat3(1.0f,0.0f,1.402f,          \
                    1.0f,-0.34414f, -0.71414f,  \
                   1.0f,1.772f,0.0f)*yuv;\n"
         "rgb.x = clamp(rgb.x, 0.0, 1.0);\n"
         "rgb.y = clamp(rgb.y, 0.0, 1.0);\n"
        "rgb.z =  clamp(rgb.z, 0.0, 1.0);\n"
        " vec3 coldColor = vec3(1.0,0.0,0.0);\n"
        "vec3 warmColor = vec3(0.0,0.0,1.0);\n"
         "vec3 adjustColor = mix(warmColor,coldColor, clamp((temperature + 1.0) * 0.5, 0.0, 1.0));\n"
         "vec4 texColor = texture(test_tex,outTexCoord);\n"
          "vec3 finColor = texColor.rgb * adjustColor;\n"
          "FragColor = texture(test_tex,outTexCoord);\n"
        "}\n\0";
void DisplayWind::initializeGL()
{ // "FragColor = texture(test_tex,outTexCoord);\n"
    initializeOpenGLFunctions();
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1,&VBO);
    glGenBuffers(1,&EBO);
    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER,VBO);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO);

    glBufferData(GL_ARRAY_BUFFER,sizeof (vers2),vers2,GL_STATIC_DRAW);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof (indecs),indecs,GL_STATIC_DRAW);
    glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,5*sizeof (GLfloat),0);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(1,2,GL_FLOAT,GL_FALSE,5*sizeof(GLfloat),(void*)(3*sizeof(GLfloat)));
    glEnableVertexAttribArray(1);

    m_shader_program = new QOpenGLShaderProgram(this);
    m_shader_program->addShaderFromSourceCode(QOpenGLShader::Vertex,vertexShaderSource);
    m_shader_program->addShaderFromSourceCode(QOpenGLShader::Fragment,fragmentShaderSource);
    bool succ = m_shader_program->link();

    if(!succ){
        LOG(ERROR) << "shader error: " << m_shader_program->log().toStdString().c_str();
    }
    m_shader_program->bind();
    trans = glm::mat4(1.0f);
    glUniformMatrix4fv(glGetUniformLocation(m_shader_program->programId(),"transform"),1,GL_FALSE,
                       glm::value_ptr(trans));
    glUniform1f(glGetUniformLocation(m_shader_program->programId(),"temperature"),1.0f);
    initTexture();
    glGenTextures(1, &m_texture);
//    glBindTexture(GL_TEXTURE_2D, m_texture);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
    glBindBuffer(GL_ARRAY_BUFFER,0);
    glBindVertexArray(0);

}
/**
//void DisplayWind::initializeGL()
{
    // 创建OpenGL上下文并设置为当前上下文
    // 在主线程中创建共享的OpenGL上下文
     m_context.setFormat(format());
     m_context.create();
     m_sharedContext.setFormat(m_context.format());
     m_sharedContext.create();
     m_sharedContext.setShareContext(&m_context);
    initializeOpenGLFunctions();
//    initVAO();
//    initShader();
    glEnable(GL_DEPTH_TEST);
    static const GLfloat vertices[]{
        //顶点坐标
        -1.0f,-1.0f,
        -1.0f,+1.0f,
        +1.0f,+1.0f,
        +1.0f,-1.0f,
        //纹理坐标
        0.0f,1.0f,
        0.0f,0.0f,
        1.0f,0.0f,
        1.0f,1.0f,
    };
     vbo.create();
     vbo.bind();
     vbo.allocate(vertices,sizeof(vertices));

     //初始化顶点着色器对象
     QOpenGLShader *vshader = new QOpenGLShader(QOpenGLShader::Vertex,this);
     //顶点着色器源码
     const char *vsrc =
    " #version 400 core \n \
     layout(location=0) in vec2 vertexIn; \
     layout(location=1) in vec2 textureIn; \
     out vec2 textureOut;  \
     void main(void)           \
     {                         \
         gl_Position = vec4(vertexIn.x,vertexIn.y,1.0f,1.0f); \
         textureOut = textureIn; \
     }";
     vshader->compileSourceCode(vsrc);	//编译顶点着色器程序
     //初始化片段着色器 功能gpu中yuv转换成rgb
      QOpenGLShader *fshader = new QOpenGLShader(QOpenGLShader::Fragment,this);
      //片段着色器源码
      const char *fsrc =
      " #version 400 core \n \
       in vec2 textureOut; \
      uniform sampler2D tex_y; \
      uniform sampler2D tex_u; \
      uniform sampler2D tex_v; \
      uniform vec3 in_color;\
      out vec4 FragColor;\
      void main(void) \
      { \
          vec3 yuv; \
          vec3 rgb; \
          FragColor = texture(tex_y,textureOut);\
      }";
      fshader->compileSourceCode(fsrc);	//将glsl源码送入编译器编译着色器程序
       GLenum error = glGetError();
             if (error != GL_NO_ERROR) {
                 // 发生了OpenGL错误
                LOG(ERROR)<< "std: OpenGL error: " << error;
        }
      //用于绘制矩形
        program = new QOpenGLShaderProgram(this);
        program->addShader(vshader);	//将顶点着色器添加到程序容器
        program->addShader(fshader);	//将片段着色器添加到程序容器
          //绑定属性vertexIn到指定位置ATTRIB_VERTEX,该属性在顶点着色源码其中有声明
      program->bindAttributeLocation("vertexIn",VERTEXIN);
          //绑定属性textureIn到指定位置ATTRIB_TEXTURE,该属性在顶点着色源码其中有声明
      error = glGetError();
       if (error != GL_NO_ERROR) {
           // 发生了OpenGL错误
          LOG(ERROR)<< "std: OpenGL error: " << error;
       }
       program->bindAttributeLocation("textureIn",TEXTUREIN);
       program->link();	//链接所有所有添入到的着色器程序
       program->bind();	 //激活所有链接
       // 检查OpenGL是否有错误
      error = glGetError();
       if (error != GL_NO_ERROR) {
           // 发生了OpenGL错误
          LOG(ERROR)<< "std: OpenGL error: " << error;
       }
       program->enableAttributeArray(VERTEXIN);
       program->setAttributeBuffer(VERTEXIN,GL_FLOAT,0,2,2*sizeof(GLfloat));
       program->enableAttributeArray(TEXTUREIN);
       program->setAttributeBuffer(TEXTUREIN,GL_FLOAT,8*sizeof(GLfloat),2,2*sizeof(GLfloat));
       error = glGetError();
              if (error != GL_NO_ERROR) {
                  // 发生了OpenGL错误
                 LOG(ERROR)<< "std: OpenGL error: " << error;
         }
       //读取着色器中的数据变量tex_y, tex_u, tex_v的位置,这些变量的声明可以在片段着色器源码中可以看到
      textureUniformY = program->uniformLocation("tex_y");
      textureUniformU = program->uniformLocation("tex_u");
      textureUniformV = program->uniformLocation("tex_v");
      in_color_id = program->uniformLocation("in_color");
      //分别创建y,u,v纹理对象
      textureY = new QOpenGLTexture(QOpenGLTexture::Target2D);
//       textureU = new QOpenGLTexture(QOpenGLTexture::Target2D);
//       textureV = new QOpenGLTexture(QOpenGLTexture::Target2D);
//       textureY->create();
//       textureU->create();
//       textureV->create();

       idY = textureY->textureId();	//获取返回y分量的纹理索引值
//       idU = textureU->textureId();	//获取返回u分量的纹理索引值
//        idV = textureV->textureId();	//获取返回v分量的纹理索引值
       glClearColor(0.0,0.0,0.0,0.0);	//设置背景色为黑色
       GLint maxTextureSize = 0;
       glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
       LOG(ERROR) << "std maxTextureSize= " << maxTextureSize;
       error = glGetError();
        if (error != GL_NO_ERROR) {
                  // 发生了OpenGL错误
                 LOG(ERROR)<< "std: OpenGL error: " << error;
       }

}
*/
void DisplayWind::resizeGL(int w, int h)
{
    //
    glViewport(0,0,w,h);
  //  req_resize_ = true;
}




void DisplayWind::allocTexture()
{

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D,g_Texture2D[Y]);
//    glTexImage2D(GL_TEXTURE_2D,0,GL_RED,dst_video_frame_.width,dst_video_frame_.height,0,GL_RED,
//                 GL_UNSIGNED_BYTE,dst_video_frame_.data[0]);
    glTexSubImage2D(GL_TEXTURE_2D,0,0,0,dst_video_frame_.width,dst_video_frame_.height,GL_RED,GL_UNSIGNED_BYTE,dst_video_frame_.data[0]);

//   glGenerateMipmap(GL_TEXTURE_2D);
    nTextureUniform[Y] = glGetUniformLocation(m_shader_program->programId(),"tex_y");
    LOG(INFO) << "tex_y = " << nTextureUniform[Y];
    glUniform1i(nTextureUniform[Y],0);





    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D,g_Texture2D[U]);
      glTexSubImage2D(GL_TEXTURE_2D,0,0,0,dst_video_frame_.width / 2,dst_video_frame_.height / 2,GL_RED,GL_UNSIGNED_BYTE,dst_video_frame_.data[1]);
//    glTexImage2D(GL_TEXTURE_2D,0,GL_RED,dst_video_frame_.width / 2,dst_video_frame_.height/2,0,GL_RED,
//                 GL_UNSIGNED_BYTE,dst_video_frame_.data[1]);
//     glGenerateMipmap(GL_TEXTURE_2D);
   nTextureUniform[U] = glGetUniformLocation(m_shader_program->programId(),"tex_u");
   glUniform1i(nTextureUniform[U],1);

//     glBindTexture(GL_TEXTURE_2D,0);
     LOG(INFO) << "tex_u = " << nTextureUniform[U];


 //  glActiveTexture(GL_TEXTURE2);
    glBindTexture(GL_TEXTURE_2D,g_Texture2D[V]);
          glTexSubImage2D(GL_TEXTURE_2D,0,0,0,dst_video_frame_.width / 2,dst_video_frame_.height / 2,GL_RED,GL_UNSIGNED_BYTE,dst_video_frame_.data[2]);
//    glTexImage2D(GL_TEXTURE_2D,0,GL_RED,dst_video_frame_.width/2,dst_video_frame_.height/2,0,GL_RED,
//                 GL_UNSIGNED_BYTE,dst_video_frame_.data[2]);
//    glGenerateMipmap(GL_TEXTURE_2D);
    nTextureUniform[V] = glGetUniformLocation(m_shader_program->programId(),"tex_v");
   glUniform1i(nTextureUniform[V],2);


   LOG(INFO) << "tex_v = " << nTextureUniform[V];

//   glActiveTexture(GL_TEXTURE0);
//   glBindTexture(GL_TEXTURE_2D,g_Texture2D[Y]);
// glActiveTexture(GL_TEXTURE1);
//  glBindTexture(GL_TEXTURE_2D,g_Texture2D[U]);
//    glActiveTexture(GL_TEXTURE2);
//   glBindTexture(GL_TEXTURE_2D,g_Texture2D[V]);


}

void DisplayWind::doRotate(enum RO_ANG type)
{
    makeCurrent();
    m_shader_program->bind();
    switch (type) {
    case RO_ANG::NORMALL:{
        trans = glm::mat4(1.0f);
        transAngle = 0;
        break;
    }
    case RO_ANG::FLIVP:{
        trans = glm::mat4(1.0f);
        trans = glm::rotate(trans,glm::radians(180.0f + 1.0f*(transAngle % 360)),glm::vec3(0.0f,0.0f,1.0f));
        transAngle += 180;
        break;
    }
    case RO_ANG::RORATE:{
        trans = glm::mat4(1.0f);
       int transAngle1 = (transAngle + 90) % 360;
        transAngle += 90;
        trans = glm::rotate(trans,glm::radians(1.0f*transAngle1), glm::vec3(0.0f,0.0f,1.0f));
        break;
    }
    default:
        trans = glm::mat4(1.0f);
        transAngle = 0;
    }
    glUniformMatrix4fv(glGetUniformLocation(m_shader_program->programId(),"transform"),1,GL_FALSE,
                       glm::value_ptr(trans));
    doneCurrent();
    update();

}

void DisplayWind::SetWarmColor()
{
    makeCurrent();
    m_shader_program->bind();
    glUniform1f(glGetUniformLocation(m_shader_program->programId(),"temperature"),1.0f);
    doneCurrent();
    update();
}

void DisplayWind::SetColdColor()
{
    makeCurrent();
    m_shader_program->bind();
    glUniform1f(glGetUniformLocation(m_shader_program->programId(),"temperature"),-1.0f);
    doneCurrent();
    update();
}

void DisplayWind::SetNorColor()
{
    makeCurrent();
    m_shader_program->bind();
    glUniform1f(glGetUniformLocation(m_shader_program->programId(),"temperature"),0.0f);
    doneCurrent();
    update();
}
void DisplayWind::paintGL()
{
    glClearColor(0.0, 0.0, 0.0, 1.0);
    glClear(GL_COLOR_BUFFER_BIT);
    float r_val = QRandomGenerator::global()->generateDouble();
    float g_val = QRandomGenerator::global()->generateDouble();
    float b_val =  QRandomGenerator::global()->generateDouble();
        m_shader_program->bind();
//    LOG(INFO) << dst_video_frame_.width << " " << dst_video_frame_.height;
//   int pos = m_shader_program->uniformLocation("s_color");
//    m_shader_program->setUniformValue(pos,r_val,g_val,b_val,1.0f);
    if(yuvPtr){
//        QOpenGLTexture t(img.mirrored());
//        LOG(INFO) << img.width() << " " << img.height();
//        int p = m_shader_program->uniformLocation("test_tex");
//        if(p==-1){
//            LOG(ERROR) << "get test_tex error: ";
//        }
//        LOG(INFO) << "p = " << p;
//         t.bind(p);

//         allocTexture();
         glBindTexture(GL_TEXTURE_2D, m_texture);
         glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
         glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
         glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
         glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
               dst_video_frame_.width, dst_video_frame_.height, 0, GL_RGB, GL_UNSIGNED_BYTE, dst_video_frame_.data[0]);
         glGenerateMipmap(GL_TEXTURE_2D); // 生成远近级别的纹理
         glUniform1i(glGetUniformLocation(m_shader_program->programId(), "test_tex"), 0);
         glActiveTexture(GL_TEXTURE0);

    }

    glBindVertexArray(VAO);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO);

    glDrawElements(GL_TRIANGLE_FAN, 4, GL_UNSIGNED_INT, 0);
//    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
    glBindVertexArray(0);
//    glBindTexture(GL_TEXTURE_2D, 0);
//    glBindTexture(GL_TEXTURE_2D, 0);
//    glBindTexture(GL_TEXTURE_2D, 0);

}

/**
//void DisplayWind::paintGL()
{
    float r_val = QRandomGenerator::global()->generateDouble();
    float g_val = QRandomGenerator::global()->generateDouble();
    float b_val =  QRandomGenerator::global()->generateDouble();
    GLenum error;
//   std::cout << "std error: " << videoW << " " << videoH;

    glClearColor(0,0,0,1.0f);
    glClear(GL_COLOR_BUFFER_BIT);
    if(this->yuvPtr == nullptr){
        LOG(ERROR) << "yuvPtr == nullptr";
        goto end;
    }

//       program->bind();	 //激活所有链接
    //------- 加载y数据纹理 -------

      glBindTexture(GL_TEXTURE_2D,idY); //绑定y分量纹理对象id到激活的纹理单元
     glActiveTexture(GL_TEXTURE0);  //激活纹理单元GL_TEXTURE0,系统里面的
     textureY = new QOpenGLTexture(img.mirrored());
    //使用内存中的数据创建真正的y分量纹理数据
//     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
//     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
//     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
//     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
//     glTexImage2D(GL_TEXTURE_2D,0,GL_RED,videoW,videoH,0,GL_RED,GL_UNSIGNED_BYTE,yuvPtr);
//     // 查询生成的纹理对象是否有效
//     if (!glIsTexture(idY)) {
//         // 纹理对象无效
//        LOG(ERROR) << "std: Generated texture is invalid.";
//         return;
//     }
//     glGenerateMipmap(GL_TEXTURE_2D); // 生成远近级别的纹理
//     //------- 加载u数据纹理 -------
//      glBindTexture(GL_TEXTURE_2D,idU);
//      glActiveTexture(GL_TEXTURE1); //激活纹理单元GL_TEXTURE1

//         //使用内存中的数据创建真正的u分量纹理数据
//      glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
//      glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
//       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
//       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
//      glTexImage2D(GL_TEXTURE_2D,0,GL_RED,videoW >> 1, videoH >> 1,0,GL_RED,GL_UNSIGNED_BYTE,yuvPtr + videoW * videoH);
//      if (!glIsTexture(idU)) {
//          // 纹理对象无效
//          LOG(ERROR) << "std: Generated texture is invalid.";
//          return;
//      }
//      glGenerateMipmap(GL_TEXTURE_2D); // 生成远近级别的纹理
//       //------- 加载v数据纹理 -------
//       glBindTexture(GL_TEXTURE_2D,idV);
//       glActiveTexture(GL_TEXTURE2); //激活纹理单元GL_TEXTURE2

//       //使用内存中的数据创建真正的v分量纹理数据
//       glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
//       glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
//       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
//       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
//       glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, videoW >> 1, videoH >> 1, 0, GL_RED, GL_UNSIGNED_BYTE, yuvPtr+videoW*videoH*5/4);
//       if (!glIsTexture(idV)) {
//           // 纹理对象无效
//             LOG(ERROR) << "std: Generated texture is invalid.";
//           return;
//       }
//        glGenerateMipmap(GL_TEXTURE_2D); // 生成远近级别的纹理
       //指定y纹理要使用新值,只能用0,1,2等表示纹理单元的索引，这是opengl不人性化的地方
        glUniform1i(textureUniformY, 0);	//0对应纹理单元GL_TEXTURE0,//指定y纹理要使用新值
        //glUniform1i(textureUniformU, 1);	//1对应纹理单元GL_TEXTURE1,//指定u纹理要使用新值
        //glUniform1i(textureUniformV, 2);	//2对应纹理的单元GL_TEXTURE2,指定v纹理要使用新值
       glUniform3f(in_color_id,r_val,g_val,b_val);
       textureY->bind(0);
        error = glGetError();
        if (error != GL_NO_ERROR) {
            // 发生了OpenGL错误
           LOG(ERROR)<< "std: OpenGL error: " << error;
        }
          //使用顶点数组方式绘制图形
end:
       glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
        if(textureY){
            delete  textureY;
        }


}
*/
/**
void DisplayWind::paintEvent(QPaintEvent *)
{
    QMutexLocker locker(&m_mutex);
     setStyleSheet("background: black");
//     makeCurrent();
     return;
    if(play_state_ == 1) {  // 播放状态
        if (img.isNull()) {
            return;
        }
        QPainter painter(this);
        painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
        //    //    p.translate(X, Y);
        //    //    p.drawImage(QRect(0, 0, W, H), img);
        QRect rect = QRect(x_, y_, img.width(), img.height());
        //        qDebug() << rect << ", win_w:" << this->width() << ", h:" << this->height();
        painter.drawImage(rect, img.scaled(img.width(), img.height()));
    } else if(play_state_ == 2) {
        QPainter p(this);
        p.setPen(Qt::NoPen);
        p.setBrush(Qt::black);
        p.drawRect(rect());
    }
}
*/

/**
//void DisplayWind::paintEvent(QPaintEvent *)
//{
//    QMutexLocker locker(&m_mutex);
//    if(play_state_ == 1) {  // 播放状态
//        if (img.isNull()) {
//            return;
//        }
//        QPainter painter(this);
//        //        painter.setRenderHint(QPainter::Antialiasing, true);
//        painter.setRenderHint(QPainter::HighQualityAntialiasing);
//        int w = this->width();
//        int h = this->height();
//        img.scaled(w, h, Qt::KeepAspectRatio, Qt::SmoothTransformation);
//        //    //    p.translate(X, Y);
//        //    //    p.drawImage(QRect(0, 0, W, H), img);
//        QRect rect = QRect(x_, y_, w, h);
//        painter.drawImage(rect, img);
//    } else if(play_state_ == 2) {
//        QPainter p(this);
//        p.setPen(Qt::NoPen);
//        p.setBrush(Qt::black);
//        p.drawRect(rect());
//    }
//}

*/
/**
void DisplayWind::resizeEvent(QResizeEvent *event)
{
    QMutexLocker locker(&m_mutex);
    if(win_width_ != width() || win_height_ != height()) {
        //        DeInit();       // 释放尺寸缩放资源，等下一次draw的时候重新初始化
        //        win_width = width();
        //        win_height = height();
        req_resize_ = true;
    }
}

*/
/**
void DisplayWind::renderYUV420P(unsigned char* yuvData, int width, int height) {
    // 初始化OpenGL
    makeCurrent();
    glClear(GL_COLOR_BUFFER_BIT);
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

    // 渲染YUV420P纹理
    GLuint tex_y, tex_u, tex_v;
    glGenTextures(1, &tex_y);
    glGenTextures(1, &tex_u);
    glGenTextures(1, &tex_v);

    // 设置Y纹理参数
    glBindTexture(GL_TEXTURE_2D, tex_y);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, yuvData);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    // 设置U纹理参数
    glBindTexture(GL_TEXTURE_2D, tex_u);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width / 2, height / 2, 0, GL_RED, GL_UNSIGNED_BYTE, yuvData + width * height);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    // 设置V纹理参数
    glBindTexture(GL_TEXTURE_2D, tex_v);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width / 2, height / 2, 0, GL_RED, GL_UNSIGNED_BYTE, yuvData + width * height * 5 / 4);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    // 渲染纹理
    glBegin(GL_QUADS);
    glTexCoord2f(0, 0); glVertex2f(-1, -1);
    glTexCoord2f(1, 0); glVertex2f(1, -1);
    glTexCoord2f(1, 1); glVertex2f(1, 1);
    glTexCoord2f(0, 1); glVertex2f(-1, 1);
    glEnd();

    // 清理纹理
    glDeleteTextures(1, &tex_y);
    glDeleteTextures(1, &tex_u);
    glDeleteTextures(1, &tex_v);
    doneCurrent();
}*/








